Skip to content

#2372: Add --retention-delay option to ide cleanup - #2378

Open
krystynaShatkovska wants to merge 8 commits into
devonfw:mainfrom
krystynaShatkovska:feature/issue-2372-retention-delay
Open

krystynaShatkovska wants to merge 8 commits into
devonfw:mainfrom
krystynaShatkovska:feature/issue-2372-retention-delay

Conversation

@krystynaShatkovska

@krystynaShatkovska krystynaShatkovska commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

This PR fixes #2372

Implemented changes:

Adds a --retention-delay option to ide cleanup. It takes an ISO-8601 duration (e.g. P30D, PT2H30M; default 1 year) and deletes stale files (not modified within that period) in $IDE_HOME/updates, $IDE_ROOT/_ide/tmp and ~/Downloads/ide. After deletion it deletes empty folders (but keeps the scanned roots). Invalid durations are rejected with a clear error.

Testing instructions

Automated tests

Run the test class, it covers all the core cases:
mvn -pl cli test -Dtest=CleanupCommandletTest

Manual test

ide cleanup scans three roots for stale files: $IDE_HOME/updates (only inside a project), $IDE_ROOT/_ide/tmp, and the download cache ~/Downloads/ide. The manual test must be run against a throwaway IDE root, not your real one, for two reasons:

  1. The download cache lives under user home (~/Downloads/ide), which is independent of IDE_ROOT. So throwaway IDE_ROOT alone would still scan (and delete from) real ~/Downloads/ide.
  2. IDE_ROOT is only used when no real IDE home is found by walking up from the working directory. If you run from inside your IDE tree, the real home is found and the IDE_ROOT override is ignored.
    So you must isolate both the IDE root and the user home, and run from a working directory outside your IDE tree. Using exec-ide.sh / mvn exec:exec does not achieve this (the forked process's working directory is the project), so the steps below invoke java directly.

Set the throwaway location once (any path outside your IDE tree, Windows example shown):

$THROW = a fresh temp directory of your choice, e.g. %TEMP%\ide-cleanup-manual
$RUN = a sibling empty directory, e.g. %TEMP%\ide-cleanup-run

  1. Build the classpath (from the repo root; regenerates cli/cp.txt with the CLI's dependency jars):

mvn -pl cli dependency:build-classpath -Dmdep.outputFile=cli/cp.txt

  1. Create the throwaway IDE root - a stale file, a fresh file, a "running" IDEasy version, and a link from _ide/installation to that running version (this is the guard under test):

Windows (PowerShell - uses a directory junction, no admin needed):
$T = "C:\Users<you>\AppData\Local\Temp\ide-cleanup-manual" # your $THROW
if (Test-Path $T) { Remove-Item $T -Recurse -Force }
New-Item -ItemType Directory -Path "$T_ide\tmp" -Force | Out-Null
New-Item -ItemType Directory -Path "$T_ide\software\maven\ideasy\default\2026.08.002" -Force |
Out-Null # running install
New-Item -ItemType Directory -Path "$T_ide\software\maven\ideasy\default\1.0" -Force | Out-Null
# unused install
New-Item -ItemType Directory -Path "$T\Downloads\ide" -Force | Out-Null
Set-Content "$T_ide\tmp\stale.bin" "x" -Force
Set-Content "$T_ide\tmp\fresh.bin" "x" -Force
(Get-Item "$T_ide\tmp\stale.bin").LastWriteTime = (Get-Date).AddDays(-31)
New-Item -ItemType Junction -Path "$T_ide\installation" -Target
"$T_ide\software\maven\ideasy\default\2026.08.002" | Out-Null
New-Item -ItemType Directory -Path "$env:TEMP\ide-cleanup-run" -Force | Out-Null # empty cwd,
outside the IDE tree

macOS / Linux (bash — uses a symlink):
T=$(mktemp -d) # your $THROW
mkdir -p "$T/_ide/tmp" "$T/_ide/software/maven/ideasy/default/2026.08.002"
"$T/_ide/software/maven/ideasy/default/1.0" "$T/Downloads/ide"
echo x > "$T/_ide/tmp/stale.bin"; echo x > "$T/_ide/tmp/fresh.bin"
touch -d "31 days ago" "$T/_ide/tmp/stale.bin" # (GNU) # macOS: touch -t
ln -s "$T/_ide/software/maven/ideasy/default/2026.08.002" "$T/_ide/installation"
mkdir -p "$TMPDIR/ide-cleanup-run"

  1. Run cleanup, fully isolated to the throwaway root. IDE_ROOT and user.home are both pointed at $THROW, so your real IDE_ROOT, your real ~/Downloads/ide, and your real software are untouched. Run from the empty working directory (not from inside your IDE tree). Answer yes twice (first = terms of use, second = "Do you want to continue?"):

Windows (Git Bash):
T='C:\Users<you>\AppData\Local\Temp\ide-cleanup-manual'
cp_file='/cli/cp.txt'
classes='/cli/target/classes'
cd "$env:TEMP/ide-cleanup-run" # empty dir, outside the IDE tree
export IDE_ROOT="$T"
CP="$classes;$(tr -d '\n' < "$cp_file")"
printf 'yes\nyes\n' | java -Duser.home="$T" -cp "$CP" com.devonfw.tools.ide.cli.Ideasy cleanup
--retention-delay=P30D

macOS / Linux:
classes="$(pwd)/cli/target/classes"; cp_file="$(pwd)/cli/cp.txt"
cd "$TMPDIR/ide-cleanup-run" # empty dir, outside the IDE tree
export IDE_ROOT="$T"
CP="$classes:$(tr -d '\n' < "$cp_file")" # note: ':' separator on unix
printf 'yes\nyes\n' | java -Duser.home="$T" -cp "$CP" com.devonfw.tools.ide.cli.Ideasy cleanup
--retention-delay=P30D

Before it deletes anything, confirm isolation: the IDE prints its resolved document path and IDE_ROOT is set to .... Both must point at your $THROW, not your real IDE root. If it prints your real root, stop - the isolation failed and it will act on your real installation.

  1. Confirm the expected results (substitute your $THROW):

$THROW/_ide/tmp/stale.bin → deleted (stale)
$THROW/_ide/tmp/fresh.bin → kept (fresh)
$THROW/_ide/software/maven/ideasy/default/1.0 → deleted (unused)
$THROW/_ide/software/maven/ideasy/default/2026.08.002 → kept (running install, guarded)

Windows:
Test-Path "$T_ide\tmp\stale.bin" # expected: False
Test-Path "$T_ide\tmp\fresh.bin" # expected: True
Test-Path "$T_ide\software\maven\ideasy\default\1.0" # expected: False
Test-Path "$T_ide\software\maven\ideasy\default\2026.08.002" # expected: True

macOS / Linux:
test -e "$T/_ide/tmp/stale.bin"; echo $? # expected 1 (False)
test -e "$T/_ide/tmp/fresh.bin"; echo $? # expected 0 (True)
test -e "$T/_ide/software/maven/ideasy/default/1.0"; echo $? # expected 1 (False)
test -e "$T/_ide/software/maven/ideasy/default/2026.08.002"; echo $? # expected 0 (True)

  1. Verify invalid --retention-delay values are rejected (same isolated setup; each must print Invalid value ... for --retention-delay and stop before doing anything):

PT6M10D # months not allowed in a time-based duration
P0D # must be positive
-P30D # must be positive
abc # not ISO-8601

(Use the same java -Duser.home="$T" -cp "$CP" ... invocation as step 3, with each value substituted for P30D.)

  1. Clean up:

rm -rf <your $THROW>


Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat and not feature/921 fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summaries what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labelled
    with internal
  • You have not changed any dependency in pom.xml files or otherwise if runtime dependencies changed, you have updated our LICENSE.asciidoc
  • You have formulated clear instructions on how to test your contribution under "Testing instructions"

Adds a --retention-delay option to the cleanup commandlet to delete stale
files that have not been modified within a configurable period. Files are
scanned recursively under $IDE_HOME/updates, $IDE_ROOT/_ide/tmp and
~/Downloads/ide.

The option accepts a time-based ISO-8601 duration (e.g. P30D) and defaults
to 1 year (365 days) if not provided. Empty folders left behind after
deleting stale files are removed, while the scanned roots themselves are kept.
@coveralls

coveralls commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 35575661066

Coverage increased (+0.1%) to 74.272%

Details

  • Coverage increased (+0.1%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 15 coverage regressions across 2 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

15 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java 14 89.65%
com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java 1 87.42%

Coverage Stats

Coverage Status
Relevant Lines: 19119
Covered Lines: 14837
Line Coverage: 77.6%
Relevant Branches: 8594
Covered Branches: 5746
Branch Coverage: 66.86%
Branches in Coverage %: Yes
Coverage Strength: 3.33 hits per line

💛 - Coveralls

@krystynaShatkovska krystynaShatkovska moved this from 🆕 New to Team Review in IDEasy board Aug 27, 2026
@samuelkos17 samuelkos17 self-assigned this Aug 27, 2026

@samuelkos17 samuelkos17 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the --retention-dely to the cleanup commandlet. I tried to follow your testing steps, however the commands you provided didn't work out for me. I've manually moved the files to /_ide/tmp though and then ran the cleanup command and it worked!
While reviewing I found some problems that could lead to issues and that really need to get addressed before moving this to In Review. You can find them in the Comments here.
Besides that I still have on recommendation:
documentation/tmp.adoc line 18 needs to be updated according to the new functionality.

Comment thread cli/src/main/resources/nls/Help.properties
Comment thread cli/src/main/resources/nls/Help_de.properties
Comment thread cli/src/main/resources/nls/Help_de.properties Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/resources/nls/Help.properties Outdated
…le stale)

- Skip symbolic links during the stale-file scan to avoid following links
  outside the scanned roots or recursing into self-referencing links
- Rename retentionDelay field to retentionDelayOption to avoid clashing
  with the local Duration variable
- Guard only the updates root on a missing IDE_HOME; the temp and download
  roots are user-level and always available
- Add test coverage and move the changelog entry to release 2026.09.002

@samuelkos17 samuelkos17 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for resolving my comments! I've tested the changes but came across another issue:
ide cleanup now wants to delete all my IDEasy installations including the one i'm currently using, the --retention-delay can have any value for that to happen, so i guess it doesn't work there. Does this problem also occur on ur end?

ide cleanup marks every installed software version that no project links to
as "unused" and deletes it. Global tools (including IDEasy itself) install
directly into the software repository and are not linked by any project, so
the currently running IDEasy installation was being deleted as well.

Resolve the running installation via the _ide/installation link and never
mark that version for deletion. Add a test that verifies the running version
is kept while genuinely unused versions are still removed, plus a
junction-based directory-link helper so the test runs on Windows without
elevated privileges.

@samuelkos17 samuelkos17 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing a guard to keep the current IDEasy installation from deleting, however while looking at your new changes I realized that the retention-delay has no impact on installed tool versions (claude, intellij, uv, ideasy). Even when you run ide cleanup with retention-delay set to any positive value the command wants to delete all installed tool versions that no project links to. I'm not quite sure if this intentional, but judging by what the issue description says I think it's not intentional and that you need to add the retention-delay checks there aswell, but please correct me if I'm wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Team Review

Development

Successfully merging this pull request may close these issues.

Implement --retention-delay option for ide cleanup (stale files in updates, _ide/tmp and ~/Downloads/ide)

3 participants